﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.Contracts;
using System.Linq;

namespace $safeprojectname$
{
    /// <summary>
    ///     Extensions available on every place of the framework.
    /// </summary>
    public static partial class Ext
    {
        #region Type GetDescriptors
        /// <summary>
        ///     returns (Cached) information about "item" properties
        /// </summary>
        /// <returns></returns>
        public static IDictionary<string, PropertyDescriptor> GetPropertyDescriptors(this Type type)
        {
            Contract.Requires(type.Is(), "Type cannot be null");
            return TypeDescriptor.GetProperties(type)
                .Cast<PropertyDescriptor>()
                .ToDictionary(
                    pd => pd.Name,
                    pd => pd);
        }

        public static bool HasType<TType>(this Type toBeCompared)
        {
            return toBeCompared.HasType(typeof (TType));
        }
        public static bool HasType(this Type toBeCompared, Type type)
        {
            if (toBeCompared.IsNull()
                || type.IsNull())
            {
                return false;
            }
            if (toBeCompared.IsEquivalentTo(type))
            {
                return true;
            }
            if (type.IsInterface)
            {
                return toBeCompared.GetInterfaces().Any(i => i.IsEquivalentTo(type));
            }
            return HasAncestor(toBeCompared, type);
        }
        static bool HasAncestor(this Type toBeCompared, Type type)
        {
            // Base types to be replaced by child
            var parent = toBeCompared.BaseType;

            while (parent.Is())
            {
                // abstract is out of scope
                if (parent.IsEquivalentTo(type))
                {
                    return true;
                }
                parent = parent.BaseType;
            }
            return false;
        }

        /// <summary>
        /// Returns true if type implements IList&lt;SomeObject&gt; where 'SomeObject' is TItem
        /// </summary>
        /// <typeparam name="TItem"></typeparam>
        /// <param name="toBeCmpared"></param>
        /// <returns></returns>
        public static bool HasTypeListOf<TItem>(this Type toBeCmpared)
        {
            var isList = toBeCmpared.IsGenericType
              && toBeCmpared.GetGenericTypeDefinition() == typeof(IList<>);

            if (!isList)
            {
                return false;
            }

            var isItemOfType = toBeCmpared
                .GetGenericArguments()[0]
                .HasType<TItem>();

            return isItemOfType;
        }
        #endregion Type GetDescriptors
    }
}